/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
 */
package td.pages;

import java.util.List;
import java.util.concurrent.TimeUnit;

import junit.framework.AssertionFailedError;

import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.jbehave.web.selenium.WebDriverPage;
import org.jbehave.web.selenium.WebDriverProvider;
import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

/**
 * @author Artem Shamsutdinov
 * 
 */
public abstract class AbstractPage extends WebDriverPage {

	private String pageName;

	public AbstractPage(WebDriverProvider driverProvider, String pageName) {
		super(driverProvider);
		this.pageName = pageName;
	}

	public String getButtonId(String buttonText) {
		throw new AssertionFailedError("Page '" + pageName
				+ "' does not have button '" + buttonText + "'");
	}

	public String getLinkId(String linkText) {
		throw new AssertionFailedError("Page '" + pageName
				+ "' does not have link '" + linkText + "'");
	}

	public String getCheckBoxId(String checkBoxText) {
		throw new AssertionFailedError("Page '" + pageName
				+ "' does not have checkbox '" + checkBoxText + "'");
	}

	public String getTextBoxId(String textBoxText) {
		throw new AssertionFailedError("Page '" + pageName
				+ "' does not have checkbox '" + textBoxText + "'");
	}

	public void found(String text) {
		found(getPageSource(), text);
	}

	public void foundByIdAndText(String id, String text) {
		WebElement element = findElement(By.id(id));
		Assert.assertNotNull("Element '" + id + "' not found", id);
		Assert.assertEquals("Text of element '" + id + "' does not match", text,
				element.getText());
	}

	public void found(String pageSource, String text) {
		if (!pageSource.contains(escapeHtml(text))) {
			Assert
					.fail("Text: '" + text + "' not found in page '" + pageSource + "'");
		}
	}

	public void found(List<String> texts) {
		for (String text : texts) {
			found(text);
		}
	}

	public void notFound(String text) {
		notFound(getPageSource(), text);
	}

	public void notFound(String pageSource, String text) {
		MatcherAssert.assertThat(pageSource.contains(escapeHtml(text)),
				Matchers.is(false));
	}

	private String escapeHtml(String text) {
		return text.replace("<", "&lt;").replace(">", "&gt;");
	}

	public WebElement foundByLabelText(String labelText) {
		WebElement element = findByLabel(labelText);
		Assert.assertNotNull("Element with label '" + labelText + "' not found",
				element);
		return element;
	}

	public WebElement foundByButtonText(String text) {
		WebElement element = findByButtonText(text);
		Assert.assertNotNull("Button with text '" + text + "' not found", element);
		return element;
	}

	public WebElement foundIdAndLabelSeparately(String id, String label) {
		WebElement element = findElement(By.id(id));
		Assert.assertNotNull("Element with id '" + id + "' not found", element);
		found(label);
		return element;
	}

	public void clickByLabel(String label) {
		WebElement labeledElement = findByLabel(label);
		Assert.assertNotNull("Element with label '" + label + "' not found",
				labeledElement);
		labeledElement.click();
	}

	protected WebElement findByLabel(String label) {
		return findElement(By.xpath("id(//label[text() = '" + label + "']/@for)"));
		// "//input[@id=//label[contains(., '" + label + "')]/@for]"
	}

	public WebElement findByButtonText(String text) {
		return findElement(By.xpath("//button[.=\"" + text + "\"]"));
		// button[.="text on button"], or //input[@value="text on button"]
	}

	public WebElement findByInputText(String text) {
		return findElement(By.xpath("//input[@value=\"" + text + "\"]"));
	}

	public void clickLinkByText(String text) {
		findElement(By.linkText(text)).click();
	}

	public void clickButtonById(String id) {
		findElement(By.id(id)).click();
	}

	public void clickButtonByText(String text) {
		foundByButtonText(text).click();
	}

	public void open(String pageUrl) {
		get(pageUrl);
		manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
	}

	public void type(String labelText, String value) {
		WebElement element = foundByLabelText(labelText);
		element.sendKeys(value);
	}

}
